import json
import logging
from concurrent.futures.thread import ThreadPoolExecutor

from django.http import HttpResponseBadRequest, HttpResponse, HttpResponseServerError

from backend.git_helper import init, get_name_and_platform, update
from backend.response_helper import to_response
from info.models import Repository, Commit, File
from task.interface import sa, nlp


def __background_worker(params):
    commits = Commit.objects.filter(repository=params[0], status=0)
    request_content = []
    for commit in commits:
        commit.status = 1
        commit.save()
        request_content.append({
            "repo_id": commit.repository_id,
            "hash": commit.hash
        })
    if len(commits) == 0:
        return
    # 具体Commit信息，需要由各模块再次请求后端来获取
    sa_results = sa(request_content)
    if len(sa_results) != len(commits):
        logging.log(level=logging.ERROR, msg="代码分析模块返回结果有问题,后台处理进程已终止")
        return
    for commit, result, request in zip(commits, sa_results, request_content):
        commit.result_sa = result["result"]
        if result["result"] != "":
            commit.status = 3
            commit.result_nlp = result["result"]
            commit.save()
            # 更新arch_line
            for key in result["detail"]:
                try:
                    file = File.objects.get(commit=commit, path=key)
                except File.DoesNotExist:
                    logging.log(level=logging.WARN, msg="代码分析模块返回结果有问题,当前Commit不涉及对应文件")
                    continue
                file.comments = json.dumps(result["detail"][key]["comments"])
                file.arch_line = json.dumps(result["detail"][key]["arch_line"])
                file.save()
            # -1的请求不发送
            request["repo_id"] = -1
        else:
            commit.status = 2
            commit.save()

    nlp_result = nlp(request_content)
    if len(nlp_result) != len(commits):
        logging.log(level=logging.ERROR, msg="自然语言处理模块返回结果有问题,后台处理进程已终止")
        return
    for commit, result, request in zip(commits, nlp_result, request_content):
        if request["repo_id"] == -1:
            continue
        commit.status = 3
        commit.result_nlp = result["result"]
        commit.save()


# 限制单线程运行
single_pool = ThreadPoolExecutor(1)

"""
GET /api/load
[参数]
url 仓库URL [必须]
[返回]
{"status": 0/-1, "msg": "...", "payload": {"repo": 仓库ID }}
当返回时,就表示仓库的基本信息已经提取完成,可以通过info接口获取
"""
def load(request):
    url = request.GET.get("url")
    if url is None:
        return to_response(-1, HttpResponseBadRequest, "请求参数错误")
    else:
        result = get_name_and_platform(url)
        if result is None:
            return to_response(-1, HttpResponseBadRequest, "请求URL不是一个有效的Git仓库")

        platform, name, hex_val = result
        try:
            repo = Repository.objects.get(platform=platform, name=name)
            exist = True
        except Repository.DoesNotExist:
            exist = False
            repo = Repository()
            repo.platform = platform
            repo.name = name
            repo.hash = hex_val
            repo.url = url
            repo.save()

        try:
            if exist:
                update(repo)
            else:
                init(repo, url)
        except ConnectionError:
            if not exist:
                # 如果新建仓库，并且产生失败，则删除
                repo.delete()
            return to_response(-1, HttpResponseServerError, "连接问题导致仓库clone或pull失败")
        repo.save()

        # __background_worker((repo,))
        single_pool.submit(__background_worker, (repo,))

        if exist:
            return to_response(0, HttpResponse, "仓库中的较旧内容已被解析，正在更新", {"repo": repo.id})
        else:
            return to_response(0, HttpResponse, "仓库已开始解析", {"repo": repo.id})

